package com.example.gobangssm.game;

import com.example.gobangssm.model.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;

//这个类表示匹配器，通过这个类完成匹配功能
@Component
public class Matcher {
    //创建三个匹配队列
    private Queue<User> normalQueue=new LinkedList<>();
    private Queue<User> highQueue=new LinkedList<>();
    private Queue<User> verHighQueue=new LinkedList<>();
    @Autowired
    private OnlineUserManager onlineUserManager;
    @Autowired
    private RoomManager roomManager;

    private ObjectMapper objectMapper=new ObjectMapper();

    public Matcher(){
        //创建三个线程，分别针对三个匹配队列进行操作
        Thread t1=new Thread(){
            @Override
            public void run() {
                //扫描 normalQueue
                while(true){
                    handlerMatch(normalQueue);
                }
            }
        };
        t1.start();
        Thread t2=new Thread(){
            @Override
            public void run() {
                while (true) {
                    handlerMatch(highQueue);
                }
            }
        };
        t2.start();

        Thread t3=new Thread(){
            @Override
            public void run() {
                while(true){
                    handlerMatch(verHighQueue);
                }
            }
        };
        t3.start();
    }

    //操作匹配队列的方法
    //把玩家放到匹配队列中
    public void add(User user){
        if(user.getScore()<2000){
            synchronized (normalQueue) {
                normalQueue.offer(user);
                normalQueue.notify();
            }
            System.out.println("把玩家"+user.getUsername()+"加入到了normal Queue");
        }else if(user.getScore()>=2000 && user.getScore()<3000){
            synchronized (highQueue) {
                highQueue.offer(user);
                highQueue.notify();
            }
            System.out.println("把玩家"+user.getUsername()+"加入到了high Queue");
        }else{
            synchronized (verHighQueue) {
                verHighQueue.offer(user);
                verHighQueue.notify();
            }
            System.out.println("把玩家"+user.getUsername()+"加入到了very HighQueue");
        }
    }

    //当玩家点击停止匹配时，就要把玩家从匹配队列中删除
    public void remove(User user){
        if(user.getScore()<2000){
            synchronized (normalQueue) {
                normalQueue.remove(user);
            }
            System.out.println("把玩家"+user.getUsername()+"移出了normal Queue");
        }else if(user.getScore()>=2000 && user.getScore()<3000){
            synchronized (highQueue) {
                highQueue.remove(user);
            }
            System.out.println("把玩家"+user.getUsername()+"移出了high Queue");
        }else{
            synchronized (verHighQueue) {
                verHighQueue.remove(user);
            }
            System.out.println("把玩家"+user.getUsername()+"移出了very HighQueue");
        }
    }

    private void handlerMatch(Queue<User> matchQueue) {
        synchronized (matchQueue) {
            try {
                //检测队列中元素个数
                //队列的初始情况可能为空，使用while进行循环检查是最合理的
                while (matchQueue.size() < 2) {
                    matchQueue.wait();
                }
                //尝试从队列中取出两个玩家
                User player1 = matchQueue.poll();
                User player2 = matchQueue.poll();
                System.out.println("匹配出两个玩家:" + player1.getUsername() + "," + player2.getUsername());
                //3. 获取到玩家的 websocket的会话
                // 获取到会话的目的是为了告诉玩家，你排到了
                WebSocketSession session1 = onlineUserManager.getFromGameHall(player1.getUserId());
                WebSocketSession session2 = onlineUserManager.getFromGameHall(player2.getUserId());
                if (session1 == null) {
                    //玩家1不在线了,把玩家2重新加回匹配队列
                    matchQueue.offer(player2);
                    return;
                }
                //玩家2不在线了，将玩家1重新加回匹配队列
                if (session2 == null) {
                    matchQueue.offer(player1);
                    return;
                }
                if (session1 == session2) {
                    //把其中的一个玩家放回匹配队列
                    matchQueue.offer(player1);
                    return;
                }
                //把两个玩家放到同一个游戏房间中
                Room room=new Room();
                roomManager.add(room,player1.getUserId(),player2.getUserId());
                //给玩家反馈信息，你匹配到对手了
                MatchResponse response1 = new MatchResponse();
                response1.setOk(true);
                response1.setMessage("matchSuccess");
                String json1 = objectMapper.writeValueAsString(response1);
                session1.sendMessage(new TextMessage(json1));

                MatchResponse response2 = new MatchResponse();
                response2.setOk(true);
                response2.setMessage("matchSuccess");
                String json2 = objectMapper.writeValueAsString(response2);
                session2.sendMessage(new TextMessage(json2));

            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
